package zhoug.common.share;

import android.Manifest;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;

import zhoug.logging.Logger;
import zhoug.common.permission.ZPermissions;
import zhoug.common.utils.AppUtils;
import zhoug.common.utils.FileUtils;
import zhoug.common.utils.IOUtils;
import zhoug.common.utils.StringUtils;
import zhoug.common.utils.TimeUtils;
import zhoug.common.utils.UriUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Locale;

import androidx.annotation.NonNull;

/**
 * @Author: 35574
 * @Date: 2022/6/23
 * @Description:
 */
public class ShareClientImp implements ShareClient {
    private static final String TAG = ">>>ShareClientImp";
    private ShareCallback mShareCallback;
    private String mAuthority;
    private Handler mMainHandler = new Handler(Looper.getMainLooper());
    private Context mContext;

    public ShareClientImp(Context context) {
        this.mContext = context;
        this.mAuthority=context.getPackageName()+".fileprovider";
    }


    @Override
    public boolean isClientValid(ClientType clientType) {
        if (clientType != ClientType.Local) {
            ClientInfo clientInfo = ClientInfo.getClientInfo(clientType);
            if (clientInfo != null) {
                return AppUtils.isAppInstalled(mContext,clientInfo.getPackageName());
            } else {
                return false;
            }
        }
        return true;
    }

    @Override
    public void setShareCallback(ShareCallback shareCallback) {
        this.mShareCallback = shareCallback;
    }

    @Override
    public void setFileProviderAuthority(String authority) {
        this.mAuthority = authority;
    }

    @Override
    public void share(@NonNull Context context, @NonNull ClientType clientType, @NonNull ShareParams shareParams) throws IllegalArgumentException {
        try {
            if (!isClientValid(clientType)) {
                shareError(new Exception(String.format(Locale.CHINA,"没有安装%s", clientType.getClientName())));
                return;
            }
            int shareType = shareParams.getShareType();
            if (shareType == ShareParams.SHARE_TYPE_TEXT && !clientType.isSupportText()) {
                shareError(new Exception(String.format(Locale.CHINA,"%s不支持分享文本", clientType.getName())));
                return;
            } else if (shareType == ShareParams.SHARE_TYPE_IMAGE && !clientType.isSupportImage()) {
                shareError(new Exception(String.format(Locale.CHINA,"%s不支持分享图片", clientType.getName())));
                return;
            } else if (shareType == ShareParams.SHARE_TYPE_HTML && !clientType.isSupportHtml()) {
                shareError(new Exception(String.format(Locale.CHINA,"%s不支持分享HTML文件", clientType.getName())));
                return;
            }

            if (clientType != ClientType.Local) {
                ClientInfo clientInfo = ClientInfo.getClientInfo(clientType);
                if (null == clientInfo) {
                    shareError(new Exception("clientInfo is null"));
                    return;
                }
                if (shareType == ShareParams.SHARE_TYPE_TEXT) {
                    //文本分享
                    shareText(context, clientInfo.getPackageName(), clientInfo.getShareClassName(), shareParams.getText());
                } else if (shareType == ShareParams.SHARE_TYPE_IMAGE) {
                    //图片分享
                    Bitmap imageData = shareParams.getImageData();
                    if (imageData != null) {
                        new Thread(() -> {
                            //bitmap保存为图片路径再分享
                            File shareFolder = FileUtils.getAppExternalCacheFolder(context, "share");
                            File file = new File(shareFolder, System.currentTimeMillis() + ".png");
                            boolean keepSuccess = bitmapToPath(imageData, file.getAbsolutePath());
                            if (!keepSuccess) {
                                shareError(new Exception("bitmap保存为图片路径失败"));
                                return;
                            }
                            mMainHandler.post(() -> shareFile(context, clientInfo.getPackageName(), clientInfo.getShareClassName(), shareType, file.getAbsolutePath()));
                        }).start();
                    } else {
                        shareFile(context, clientInfo.getPackageName(), clientInfo.getShareClassName(), shareType, shareParams.getFilePath());
                    }
                } else if (shareType == ShareParams.SHARE_TYPE_HTML) {
                    //html文件分享
                    shareFile(context, clientInfo.getPackageName(), clientInfo.getShareClassName(), shareType, shareParams.getFilePath());
                }
            } else {
                //保存本地
                ZPermissions.with(context)
                        .setPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
                        .setDescription("保存本地需要储存权限")
                        .setShowNoAsking(true)
                        .setCallback((success, granted, denied) -> {
                            if (success) {
                                localShare(context, shareParams);
                            }
                        }).request();
            }
        } catch (Exception e) {
            e.printStackTrace();
            Logger.e(TAG, "分享失败:" + e.getMessage());
        }
    }

    /**
     * 分享文本
     *
     * @param context
     * @param packageName
     * @param componentClassName
     * @param text
     */
    private void shareText(@NonNull Context context, @NonNull String packageName, @NonNull String componentClassName, @NonNull String text) {
        try {
            final Intent shareIntent = new Intent();
            shareIntent.setAction(Intent.ACTION_SEND);
            shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            shareIntent.setType("text/*");
            ComponentName comp = new ComponentName(packageName, componentClassName);
            shareIntent.setComponent(comp);
            shareIntent.putExtra(Intent.EXTRA_TEXT, text);
            context.startActivity(shareIntent);
        } catch (Exception e) {
            e.printStackTrace();
            Logger.e(TAG, "shareText:" + e.getMessage());
        }
    }

    /**
     * 分享文件
     *
     * @param context
     * @param packageName
     * @param componentClassName
     * @param path
     */
    private void shareFile(@NonNull Context context, @NonNull String packageName, @NonNull String componentClassName, int shareType, @NonNull String path) {
        try {
            if (StringUtils.isNullOrEmpty(path)) {
                shareError(new Exception("分享文件路径为空"));
                return;
            }
            File file = new File(path);
            if (!file.exists()) {
                shareError(new Exception("分享文件不存在"));
                return;
            }
            final Intent shareIntent = new Intent();
            shareIntent.setAction(Intent.ACTION_SEND);
            shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    |Intent.FLAG_ACTIVITY_CLEAR_TOP
                    |Intent.FLAG_ACTIVITY_SINGLE_TOP);
            Uri uri = UriUtils.getUriForFile(context, path, mAuthority);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                context.grantUriPermission(context.getPackageName(), uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
                shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            }
            shareIntent.setType(getMimeType(shareType));
            ComponentName comp = new ComponentName(packageName, componentClassName);
            shareIntent.setComponent(comp);
            shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
            context.startActivity(shareIntent);
        } catch (Exception e) {
            e.printStackTrace();
            Logger.e(TAG, "shareImage:" + e.getMessage());
        }
    }

    private String getMimeType(int shareType) {
        if (shareType == ShareParams.SHARE_TYPE_IMAGE) {
            return "image/*";
        } else if (shareType == ShareParams.SHARE_TYPE_HTML) {
            return "text/html";
        }
        return "application/octet-stream";
    }

    /**
     * 本地保存
     */
    private void localShare(Context context, final ShareParams shareParams) throws IllegalArgumentException {
        int shareType = shareParams.getShareType();
        switch (shareType) {
            case ShareParams.SHARE_TYPE_IMAGE://图片保存本地
                new Thread(() -> {
                    String imagePath = shareParams.getFilePath();
                    String localPath = shareParams.getKeepLocalPath();
                    if (localPath == null) {
                        if (imagePath != null) {
                            String fileName = FileUtils.getNameWithOutSuffix(imagePath);
                            String suffix = FileUtils.getSuffix(imagePath, true);
                            fileName = fileName + "_" + TimeUtils.getCurrentTime("yyyyMMddHHmmss_SSS") + suffix;
                            localPath = new File(FileUtils.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), fileName).getAbsolutePath();
                        } else {
                            //随机生成文件名
                            localPath = new File(FileUtils.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), TimeUtils.getCurrentTime("yyyyMMddHHmmss_SSS") + ".png").getAbsolutePath();
                        }
                    }
                    final String keepPath = localPath;
                    Bitmap imageData = shareParams.getImageData();
                    if (imageData != null) {
                        boolean b = bitmapToPath(imageData, keepPath);
                        if (b) {
                            AppUtils.scannerFile(context, keepPath);
                            if (mShareCallback != null) {
                                mMainHandler.post(() -> mShareCallback.onKeepLocalSuccess(keepPath));
                            }
                        } else {
                            shareError(new Exception("保存图片失败"));
                        }
                    } else {
                        boolean b = IOUtils.copyFile(imagePath, keepPath);
                        if (b) {
                            AppUtils.scannerFile(context, keepPath);
                            if (mShareCallback != null) {
                                mMainHandler.post(() -> mShareCallback.onKeepLocalSuccess(keepPath));
                            }
                        } else {
                            shareError(new Exception("保存图片失败"));
                        }
                    }
                }).start();
                break;
            case ShareParams.SHARE_TYPE_HTML://HTML保存
                new Thread(() -> {
                    String filePath = shareParams.getFilePath();
                    String localPath = shareParams.getKeepLocalPath();
                    if (localPath == null) {
                        if (filePath != null) {
                            String fileName = FileUtils.getNameWithOutSuffix(filePath);
                            String suffix = FileUtils.getSuffix(filePath, true);
                            fileName = fileName + "_" + TimeUtils.getCurrentTime("yyyyMMddHHmmss_SSS") + suffix;
                            localPath = new File(FileUtils.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), fileName).getAbsolutePath();
                        } else {
                            //随机生成文件名
                            localPath = new File(FileUtils.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), TimeUtils.getCurrentTime("yyyyMMddHHmmss_SSS") + ".html").getAbsolutePath();
                        }
                    }
                    final String keepPath = localPath;
                    boolean b = IOUtils.copyFile(filePath, keepPath);
                    if (b) {
                        AppUtils.scannerFile(context, keepPath);
                        if (mShareCallback != null) {
                            mMainHandler.post(() -> mShareCallback.onKeepLocalSuccess(keepPath));
                        }
                    } else {
                        shareError(new Exception("保存文件失败"));
                    }
                }).start();
                break;
            case ShareParams.SHARE_TYPE_TEXT://文本分享
                new Thread(() -> {
                    String localPath = shareParams.getKeepLocalPath();
                    if (localPath == null) {
                        localPath = new File(FileUtils.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), TimeUtils.getCurrentTime("yyyyMMddHHmmss_SSS") + ".txt").getAbsolutePath();
                    }
                    final String keepPath = localPath;
                    String text = shareParams.getText();
                    FileOutputStream fos = null;
                    try {
                        AppUtils.copyContentToClipboard(context, "文本分享", text);
                        fos = new FileOutputStream(keepPath);
                        byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
                        fos.write(bytes, 0, bytes.length);
                        fos.flush();
                        fos.close();
                        fos = null;
                        if (mShareCallback != null) {
                            mMainHandler.post(() -> mShareCallback.onKeepLocalSuccess("已复制到剪切板并保存到文件中:" + keepPath));
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        shareError(e);
                    } finally {
                        IOUtils.close(fos);
                    }
                }).start();


                break;
        }

    }

    /**
     * 分享失败触发ShareCallback.onShareError
     *
     * @param error
     */
    private void shareError(Throwable error) {
        error.printStackTrace();
        Logger.e(TAG, "shareError:" + error.getMessage());
        if (mShareCallback != null) {
            mMainHandler.post(() -> mShareCallback.onShareError(error));
        }
    }


    /**
     * Bitmap 保存为文件
     *
     * @param bitmap
     * @param path   bitmap保存路径
     * @return
     */
    private boolean bitmapToPath(Bitmap bitmap, String path) {
        FileOutputStream fos = null;
        boolean compress;
        try {
            fos = new FileOutputStream(path);
            compress = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            if (compress) {
                fos.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
            compress = false;
            Logger.e(TAG, "保存bitmap图片失败");
        } finally {
            IOUtils.close(fos);
        }
        return compress;
    }



}
